這幾天看了很多關於函式中 this
的文章,但感覺還不是很懂 XDDD,今天要來跟著這個影片來學習傳統函式跟箭頭函式中 this
的差別,練練我的小腦袋!
如果想了解詳細關於 this 的介紹,以下好文推推歐 ^___^:
Huli:淺談 JavaScript 頭號難題 this:絕對不完整,但保證好懂
卡斯伯:JavaScript 的 this 到底是誰?
卡斯伯:箭頭函式 (Arrow functions)
綁定的 this
不同
傳統函式:this 會依照
呼叫的方法
而定,並非宣告的時機
箭頭函式:this 會綁定到其定義時所在的物件
我們有一個物件 rabbit
,裡面記錄某隻兔子的姓名跟日常興趣,還有一個函式搭配 map()
方法用來 console.log
出兔子的姓名跟興趣,如果用傳統函式
的話就會這樣寫:
const rabbit = {
name: '泡泡',
daily: ['耍廢','放空','裝可愛'],
printDaily: function() {
this.daily.map(function(item){
console.log(`${this.name} 每天都在 ${item}`);
})
}
}
rabbit.printDaily();
來看一下結果:
邪門囉,我的泡泡不見了!
看來是 map()
方法中的 this.name
出了問題,這邊的 this
值是什麼呢?我們來確認一下:
const rabbit = {
name: '泡泡',
daily: ['耍廢','放空','裝可愛'],
printDaily: function() {
this.daily.map(function(item){
console.log(this); // window 物件
})
}
}
rabbit.printDaily();
在 map()
裡的 this
綁定到了 window
物件。
原因是因為: 傳統函式宣告的位置
並不會影響 this
指向的值,重要的是呼叫的方法
,如果是純粹的呼叫傳統函式的話,無論放在什麼位置,這個 this
都會指向全域,而 map()
方法裡的函式,是 map()
方法內的回調函數,他是一個獨立函數,不是被當作物件的方法調用,這個時候這個獨立函數裡面的 this
就會指向 window
了。
那如果我們是在物件的方法中呼叫 this
的話呢?
const rabbit = {
name: '泡泡',
daily: ['耍廢','放空','裝可愛'],
printDaily: function() {
console.log(this); // rabbit 物件
}
}
rabbit.printDaily();
這裡的 this
綁定到了 rabbit
物件。
原因是因為: 如果 function
是在物件下調用,那麼 this
則會指向此物件,無論 function
是在哪裡宣告。
所以在過去的作法,我們會另外宣告一個變數賦值 this
的值,像是這樣:
const rabbit = {
name: '泡泡',
daily: ['耍廢','放空','裝可愛'],
printDaily: function() {
let self = this;
this.daily.map(function(item){
console.log(`${self.name} 每天都在 ${item}`);
})
}
}
rabbit.printDaily();
來看看結果:
這樣就可以成功取得泡泡的名稱囉!
但如果我們把 map()
方法內的函式改成箭頭函式呢?
const rabbit = {
name: '泡泡',
daily: ['耍廢','放空','裝可愛'],
printDaily: function() {
this.daily.map(item => {
console.log(`${this.name} 每天都在 ${item}`)
})
}
}
rabbit.printDaily();
console 畫面:
哦!成功綁定到泡泡物件了!這是為什麼呢?
那是因為: 箭頭函式的 this
值會繼承他的父作用域,跟傳統函式「根據呼叫的方式而定」不同,箭頭函式是在定義時就被指定了
,以後也不會隨著呼叫方法改變,所以我們這個例子中的 this
值就會調用他的父作用域的 this
值「泡泡物件」,所以我們就能正確得到泡泡的名稱囉!
如果今天我想要函式中的 this
值綁定父作用域的 this
值、並且不希望他在調用時被改變時,那就可以使用箭頭函式囉!